unit fCirclein3D;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  System.Math,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.ComCtrls,

  GLS.Objects,
  GLS.Scene,
  Vcl.StdCtrls,
  GLS.SceneViewer,
  GLS.Coordinates,
  GLS.BaseClasses,
  GLS.SimpleNavigation;

type
  TForm1 = class(TForm)
    GLScene1: TGLScene;
    GLSceneViewer1: TGLSceneViewer;
    sbSegments: TScrollBar;
    Label1: TLabel;
    Camera: TGLCamera;
    LightSource: TGLLightSource;
    dcMeridian: TGLDummyCube;
    Meridian: TGLLines;
    Label2: TLabel;
    sbWidth: TScrollBar;
    Label3: TLabel;
    sbHeight: TScrollBar;
    Label4: TLabel;
    ScrollBar4: TScrollBar;
    chbSpline: TCheckBox;
    GLSimpleNavigation1: TGLSimpleNavigation;
    chbNodes: TCheckBox;
    chbDash: TCheckBox;
    Parallel: TGLLines;
    StatusBar1: TStatusBar;
    dcParallel: TGLDummyCube;
    dcGeogrid: TGLDummyCube;
    Merid1: TGLLines;
    Paral1: TGLLines;
    Sphere: TGLSphere;
    procedure chbSplineClick(Sender: TObject);
    procedure sbCircleChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure chbNodesClick(Sender: TObject);
    procedure chbDashClick(Sender: TObject);
  private
  public
    procedure BuildParallels;
    procedure BuildOrbit;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
{ TForm1 }

// ---------------------------------------------------------------------------
procedure TForm1.BuildParallels;
var
  A, B: Double;
  I, Segments: Integer;
  RotationAngle, theta: Double;
  x, y, xCenter, xRotated: Double;
  yCenter, yRotated: Double;

begin
  Segments := sbSegments.Position;
  A := sbWidth.Position / 100;
  B := sbHeight.Position / 100;
  RotationAngle := DegToRad(ScrollBar4.Position);

  Meridian.Nodes.Clear;

  xCenter := 0;
  yCenter := 0;
  for I := 0 to Segments do
  begin
    theta := 360 * (I / Segments) * (PI / 180);

    x := xCenter + A * Cos(theta);
    y := yCenter + B * Sin(theta);
    xRotated := xCenter + (x - xCenter) * Cos(RotationAngle) - (y - yCenter) *
      Sin(RotationAngle);
    yRotated := yCenter + (x - xCenter) * Sin(RotationAngle) + (y - yCenter) *
      Cos(RotationAngle);

    Meridian.Nodes.AddNode(xRotated, 0, yRotated);
    // Meridian.PitchAngle := 90;
  end;
end;

// ---------------------------------------------------------------------------
procedure TForm1.BuildOrbit;
var
  A, B: Double;
  I: Integer;
  theta: Double;
  x, y, xCenter, xRotated: Double;
  yCenter, yRotated: Double;

const
  Segments = 32;
  circleWidth = 1;
  circleHeight = 1;
  RotationAngle = 0;

begin
  A := circleWidth;
  B := circleHeight;

  Parallel.Nodes.Clear;

  xCenter := 0;
  yCenter := 0;
  for I := 0 to Segments do
  begin
    theta := 360 * (I / Segments) * (PI / 180);

    x := xCenter + A * Cos(theta);
    y := yCenter + B * Sin(theta);
    xRotated := xCenter + (x - xCenter) * Cos(RotationAngle) - (y - yCenter) *
      Sin(RotationAngle);
    yRotated := yCenter + (x - xCenter) * Sin(RotationAngle) + (y - yCenter) *
      Cos(RotationAngle);

    Parallel.Nodes.AddNode(xRotated, 0, yRotated);
    Parallel.PitchAngle := 90;
  end;
end;

// ---------------------------------------------------------------------------
procedure TForm1.FormCreate(Sender: TObject);
begin
  BuildParallels;
  BuildOrbit;
end;

// ---------------------------------------------------------------------------
procedure TForm1.sbCircleChange(Sender: TObject);
begin
  BuildParallels;
end;

// ---------------------------------------------------------------------------
procedure TForm1.chbNodesClick(Sender: TObject);
begin
  if chbNodes.Checked then
  begin
    Meridian.NodesAspect := lnaCube;
    Meridian.NodeSize := 0.05;
  end
  else
  begin
    Meridian.NodesAspect := lnaInvisible;
    Meridian.NodeSize := 0.005;
  end;
end;

// ========================================================================
procedure TForm1.chbSplineClick(Sender: TObject);
begin
  if chbSpline.Checked then
    Meridian.SplineMode := lsmCubicSpline
  else
    Meridian.SplineMode := lsmLines;
end;

procedure TForm1.chbDashClick(Sender: TObject);
begin
  if chbDash.Checked then
    Meridian.SplineMode := lsmSegments
  else
    Meridian.SplineMode := lsmLines;
end;

end.
